package com.example.algorithm;

import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;

/**
 * 拓扑排序
 *
 * @author
 * @DATE 2024/6/22
 **/
public class TopologicalSort {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in, StandardCharsets.UTF_8.name());
        int taskNum = cin.nextInt();
        int relationNum = cin.nextInt();
        int[][] relations = new int[relationNum][];
        if (relationNum > 0) {
            cin.nextLine();
            for (int i = 0; i < relationNum; i++) {
                String[] str = cin.nextLine().split(">");
                relations[i] = new int[2];
                relations[i][0] = Integer.parseInt(str[0]);
                relations[i][1] = Integer.parseInt(str[1]);
            }
        }
        cin.close();
        System.out.println(getMinTime(taskNum, relations));
    }

    private static int getMinTime(int taskNum, int[][] relations) {
        /**
         * 创建拓扑排序
         * 创建一个入度表
         * 遍历入度表，把入读为0的全部入队列
         * 队列出队，判断当前任务的入度是否为0，如果为0，加入队列，遍历完成就是最少次数
         */
        if (taskNum == 0) {
            return 0;
        }
        // 记录每个节点入度
        int[] num = new int[taskNum];
        for (int i = 0; i < relations.length; i++) {
            // 入度指的是一个点被多个边指向
            num[relations[i][0]]++;
        }
        Queue<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < taskNum; i++) {
            // 首先将入度为0的点添加到队列
            if (num[i] == 0) {
                queue.add(i);
            }
        }

        int time = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                // 当前节点出队时，将该节点的入度-1
                int temp = queue.poll();
                for (int j = 0; j < relations.length; j++) {
                    // relations[j][1]代表依赖节点 == 当前出队节点
                    if (relations[j][1] == temp) {
                        // 当前节点入度-1
                        num[relations[j][0]]--;
                        if (num[relations[j][0]] == 0) {
                            // 入度为0的当前节点，加入队列
                            queue.add(relations[j][0]);
                        }
                    }
                }
            }
            time++;
        }
        return time;
    }
}
